package com.chem.lems.serves.impl;

import com.chem.lems.constans.EquipStateCinstant;
import com.chem.lems.constans.ResultCodeConstant;
import com.chem.lems.entity.Equipment;
import com.chem.lems.entity.Record;
import com.chem.lems.entity.User;
import com.chem.lems.repository.EquipmentRepository;
import com.chem.lems.repository.RecordRepository;
import com.chem.lems.repository.UserRepository;
import com.chem.lems.serves.EquipmentServies;
import com.chem.lems.utils.ResultUtil;
import com.chem.lems.vo.ApplyBO;
import com.chem.lems.vo.EmailBO;
import com.chem.lems.vo.EquipStateVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import javax.mail.internet.MimeMessage;
import java.util.*;

@Service
public class EquipmentServiesImpl implements EquipmentServies {
    @Autowired
    private EquipmentRepository equipmentRepository;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private RecordRepository recordRepository;
    @Autowired
    private JavaMailSender mailSender;
    @Autowired
    private Environment env;

    /**
     * 生成设备状态的枚举值
     *
     * @return
     */
    @Override
    public ResultUtil getEquipStatesEnum() {
        List<EquipStateVO> list = new ArrayList<>();
        list.add(new EquipStateVO("空闲中", EquipStateCinstant.IDLE.code()));
        list.add(new EquipStateVO("预约中", EquipStateCinstant.APPOINMENT.code()));
        list.add(new EquipStateVO("借出中", EquipStateCinstant.LENDING.code()));
        list.add(new EquipStateVO("归还中", EquipStateCinstant.RESTITUTION.code()));
        list.add(new EquipStateVO("已损坏", EquipStateCinstant.DAMAGRED.code()));
        list.add(new EquipStateVO("维修中", EquipStateCinstant.MAINTENANCE.code()));
        return new ResultUtil(ResultCodeConstant.SUCCESS, "获取设备状态列表成功！", list);
    }

    /**
     * 添加设备
     *
     * @param equipment
     * @return
     */
    @Override
    public ResultUtil addEquipment(Equipment equipment) {
        equipment.setCreateTime(new Date());
        Equipment equip = equipmentRepository.save(equipment);
        if (null != equip) {
            return new ResultUtil(ResultCodeConstant.SUCCESS, "设备添加成功！");
        }
        return new ResultUtil(ResultCodeConstant.FAIL, "设备添加失败！");
    }

    /**
     * 获取全部设备列表 分页
     *
     * @param page
     * @param size
     * @return
     */
    @Override
    public ResultUtil gitEquipByAll(Integer page, Integer size) {
        PageRequest pageRequest = PageRequest.of(page, size);
        Page<Equipment> pageList = equipmentRepository.findAll(pageRequest);
        long total = pageList.getTotalElements();
        List<Equipment> userList = pageList.getContent();
        Map<String, Object> userMap = new HashMap<>();
        userMap.put("equips", userList);
        userMap.put("total", total);
        return new ResultUtil(ResultCodeConstant.SUCCESS, "获取设备列表成功！", userMap);
    }

    @Override
    /**
     * 模糊查询用户列表 分页
     *
     * @param username
     * @param page
     * @param size
     * @return
     */
    public ResultUtil gitEquipByNameLike(String equipName, Integer page, Integer size) {
        PageRequest pageRequest = PageRequest.of(page, size);
        Map<String, Object> userMap = new HashMap<>();
        List<Equipment> userList = new ArrayList<>();
        long total = 0;
        if (equipName.length() == 32) {
            Optional<Equipment> equipmentOpt = equipmentRepository.findById(equipName);
            if (equipmentOpt.isPresent()) {
                Equipment equipment = equipmentOpt.get();
                userList.add(equipment);
                total = 1;
            }
        } else {
            Page<Equipment> pageList = equipmentRepository.findByNameLike(equipName, pageRequest);
            total = pageList.getTotalElements();
            userList = pageList.getContent();
        }

        userMap.put("equips", userList);
        userMap.put("total", total);
        return new ResultUtil(ResultCodeConstant.SUCCESS, "查找设备成功！", userMap);
    }

    /**
     * 根据设备名称查询设备信息
     *
     * @param equipId
     * @return
     */
    @Override
    public ResultUtil gitEquipInfoById(String equipId) {
        Equipment equipment = equipmentRepository.findById(equipId).get();
        return new ResultUtil(ResultCodeConstant.SUCCESS, "获取设备信息成功！", equipment);
    }

    /**
     * 修改用户信息
     *
     * @param equipment
     * @return
     */
    @Override
    public ResultUtil editEquipInfo(Equipment equipment) {
        Equipment result = equipmentRepository.save(equipment);
        if (result == null) {
            return new ResultUtil(ResultCodeConstant.FAIL, "设备信息修改失败！", result);
        }
        return new ResultUtil(ResultCodeConstant.SUCCESS, "设备信息修改成功！", result);
    }

    /**
     * 删除设备
     *
     * @param equipId
     * @return
     */
    @Override
    public ResultUtil deleteById(String equipId) {
        equipmentRepository.deleteById(equipId);
        return new ResultUtil(ResultCodeConstant.SUCCESS, "设备编号为" + equipId + "的设备删除成功！");
    }

    @Override
    public ResultUtil getUserByEquipId(String equipId) {
        String userId = equipmentRepository.findUserIdByequipId(equipId);
        if (null != userId) {
            User user = userRepository.findById(userId).get();
            if (user != null) {
                return new ResultUtil(ResultCodeConstant.SUCCESS, "查询成功！", user);
            }
        }
        return new ResultUtil(ResultCodeConstant.FAIL, "查询失败");
    }

    /**
     * 设备预约申请
     *
     * @param userId
     * @param equipId
     * @return
     */
    @Override
    public ResultUtil applyEquip(String userId, String equipId) {
        equipmentRepository.addApplyInfo(userId, equipId);
        Integer result = equipmentRepository.updataEquipState(EquipStateCinstant.APPOINMENT.code(), equipId);
        if (result == 0) {
            return new ResultUtil(ResultCodeConstant.FAIL, "提交申请失败，请重新提交！");
        }
        return new ResultUtil(ResultCodeConstant.SUCCESS, "提交申请成功，请等待邮箱通知", result);
    }


    /**
     * 获取需要审核的设备列表
     *
     * @param page
     * @param size
     * @return
     */
    @Override
    public ResultUtil getRecordList(Integer page, Integer size) {
        int equipState = EquipStateCinstant.APPOINMENT.code();
        List<Equipment> result = equipmentRepository.getRecordList(equipState, page, size);
        if (result == null) {
            return new ResultUtil(ResultCodeConstant.FAIL, "待审核列表为空！");
        }
        return new ResultUtil(ResultCodeConstant.SUCCESS, "获取待审核列表成功！", result);
    }

    /**
     * 预约的审核
     *
     * @param applyBO
     * @return
     */
    @Override
    public ResultUtil applyReview(ApplyBO applyBO) {
        Record record = applyBO.getRecordObj();
        EmailBO emailBO = applyBO.getEmailObj();
        String toEmail = userRepository.findEmailById(record.getUserId());
        if (env.getProperty("spring.mail.password").equals(emailBO.getEmailPassword())) {
            // 登录邮件
            try {
                MimeMessage mimeMessage = mailSender.createMimeMessage();
                MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
                messageHelper.setFrom(env.getProperty("spring.mail.username"));
                messageHelper.setTo(toEmail);
                messageHelper.setSubject("设备预约邮件通知");
                messageHelper.setText(emailBO.getNotice(), true);
                mailSender.send(mimeMessage);
            } catch (Exception e) {
                return new ResultUtil(ResultCodeConstant.FAIL, "通知邮件发送失败！");
            }
            if (emailBO.isState()) {
                return applyReviewPass(record);
            }
            return applyReviewRefuse(record);
        }
        return new ResultUtil(ResultCodeConstant.FAIL, "邮箱授权码错误！");
    }


    /**
     * 获取用户关联的全部设备列表
     *
     * @param userId
     * @return
     */
    @Override
    public ResultUtil gitUserEquips(String userId) {
        User result = userRepository.findById(userId).get();
        List<Equipment> pageList = result.getEquipments();
        if (pageList == null) {
            return new ResultUtil(ResultCodeConstant.FAIL, "无数据！");
        }
        return new ResultUtil(ResultCodeConstant.SUCCESS, "待操作设备列表获取成功！", pageList);
    }

    /**
     * 取消设备预约
     *
     * @param userId
     * @param equipId
     * @return
     */
    @Override
    public ResultUtil cancelApply(String userId, String equipId) {
        equipmentRepository.deleteUserEquip(userId, equipId);
        Integer result = equipmentRepository.updataEquipState(EquipStateCinstant.IDLE.code(), equipId);
        if (result == 0) {
            return new ResultUtil(ResultCodeConstant.FAIL, "预约取消失败，请重新提交！");
        }
        return new ResultUtil(ResultCodeConstant.SUCCESS, "成功取消预约！");
    }

    /**
     * 归还设备
     *
     * @param userId
     * @param equipId
     * @return
     */
    @Override
    public ResultUtil backlEquip(String userId, String equipId) {
        Integer result = equipmentRepository.updataEquipState(EquipStateCinstant.RESTITUTION.code(), equipId);
        if (result == 0) {
            return new ResultUtil(ResultCodeConstant.FAIL, "设备归还申请失败，请重新提交！");
        }
        return new ResultUtil(ResultCodeConstant.SUCCESS, "设备归还申请成功！");
    }

    /**
     * 设备归还确认
     *
     * @param userId
     * @param equipId
     * @return
     */
    public ResultUtil backReview(String userId, String equipId) {
        equipmentRepository.deleteUserEquip(userId, equipId);
        Integer result = equipmentRepository.updataEquipState(EquipStateCinstant.IDLE.code(), equipId);
        if (result == 0) {
            return new ResultUtil(ResultCodeConstant.FAIL, "审核通过失败，请重新提交！");
        }
        Record newRecord = recordRepository.findrecord(userId, equipId);
        newRecord.setBackTime(new Date());
        Record record = recordRepository.save(newRecord);
        if (record == null) {
            return new ResultUtil(ResultCodeConstant.FAIL, "审核通过失败，请重新提交！");
        }
        return new ResultUtil(ResultCodeConstant.SUCCESS, "审核通过！", newRecord);
    }

    /**
     * 取消设备归还
     *
     * @param userId
     * @param equipId
     * @return
     */
    @Override
    public ResultUtil cancelBack(String userId, String equipId) {
        Integer result = equipmentRepository.updataEquipState(EquipStateCinstant.LENDING.code(), equipId);
        if (result == 0) {
            return new ResultUtil(ResultCodeConstant.FAIL, "取消归还失败，请重新提交！");
        }
        return new ResultUtil(ResultCodeConstant.SUCCESS, "成功取消归还！");
    }

    /**
     * 获取需要确认的设备列表
     *
     * @param page
     * @param size
     * @return
     */
    @Override
    public ResultUtil getverifyList(Integer page, Integer size) {
        int equipState = EquipStateCinstant.RESTITUTION.code();
        List<Equipment> result = equipmentRepository.getRecordList(equipState, page, size);
        if (result == null) {
            return new ResultUtil(ResultCodeConstant.FAIL, "待归还确认列表为空！");
        }
        return new ResultUtil(ResultCodeConstant.SUCCESS, "获取待归还确认列表成功！", result);
    }

    /**
     * 设备预约审核通过
     */
    public ResultUtil applyReviewPass(Record record) {
        Integer result = equipmentRepository.updataEquipState(EquipStateCinstant.LENDING.code(), record.getEquipId());
        if (result == 0) {
            return new ResultUtil(ResultCodeConstant.FAIL, "审核通过失败，请重新提交！");
        }
        String userName = userRepository.findById(record.getUserId()).get().getNikeName();
        String EquipName = equipmentRepository.findById(record.getEquipId()).get().getEquipName();
        record.setUserName(userName);
        record.setEquipName(EquipName);
        Record newRecord = recordRepository.save(record);
        return new ResultUtil(ResultCodeConstant.SUCCESS, "审核通过！", newRecord);
    }

    /**
     * 设备预约审核驳回
     */
    public ResultUtil applyReviewRefuse(Record record) {
        Integer result = equipmentRepository.updataEquipState(EquipStateCinstant.IDLE.code(), record.getEquipId());
        if (result == 0) {
            return new ResultUtil(ResultCodeConstant.FAIL, "驳回失败，请重新提交！");
        }
        equipmentRepository.deleteUserEquip(record.getUserId(), record.getEquipId());
        return new ResultUtil(ResultCodeConstant.SUCCESS, "驳回成功！");
    }
}
